﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Reflection;
using System.Collections;
using System.Data;

namespace SAPBoAddonUI
{
    /// <summary>
    /// 负责多语言的转换
    /// </summary>
    /// <author>Webb.Wen</author>
    /// <lastedit>2011-07-12 11:39:25</lastedit>
    public class Translater
    {
        #region 语言翻译过程中的事件（就写了一个）
        /// <summary>
        /// 当键值对无法和srf匹配时的事件委托
        /// </summary>
        /// <param name="key">键</param>
        /// <param name="value">值</param>
        public delegate void ElementNoFoundHandler(string key, string value);
        public event ElementNoFoundHandler ElementNoFoundEvent;
        #endregion

        #region 创建语言包
        public B1FormLanguagePackage CreateLanguagePackage(XmlDocument xml)
        {
            B1FormLanguagePackage package = new B1FormLanguagePackage();
            XmlNode root = xml.SelectSingleNode("Application");
            foreach (XmlNode subXmlnod in root.ChildNodes)
            {
                InitLanguagePackage(subXmlnod.ChildNodes, package);
            }
            return package;
        }
        /// <summary>
        /// 根据Application节点初始化语言包
        /// </summary>
        /// <param name="nodes"></param>
        /// <param name="package"></param>
        private void InitLanguagePackage(XmlNodeList nodes, B1FormLanguagePackage package)
        {
            //遍历+递归
            foreach (XmlNode node in nodes)
            {
                if (node.Attributes != null)
                {
                    if (node.Name == "form")
                    {
                        package.Appformnumber = node.Attributes["appformnumber"] == null ? "" : node.Attributes["appformnumber"].Value;
                        package.FormType = node.Attributes["FormType"] == null ? "" : node.Attributes["FormType"].Value;
                        package.Uid = node.Attributes["uid"] == null ? "" : node.Attributes["uid"].Value;
                        package.Title = node.Attributes["title"] == null ? "" : node.Attributes["title"].Value;
                        package.Type = node.Attributes["type"] == null ? "" : node.Attributes["type"].Value;
                        package.ObjectType = node.Attributes["ObjectType"] == null ? "" : node.Attributes["ObjectType"].Value;
                    }
                    else
                    {
                        string type = node.Attributes["type"] == null ? null : node.Attributes["type"].Value;
                        if (!String.IsNullOrEmpty(type))
                        {
                            #region BoFormItemTypes
                            /*
                 *  it_BUTTON = 4,
                    it_STATIC = 8,
                    it_EDIT = 16,
                    it_FOLDER = 99,
                    it_RECTANGLE = 100,
                    it_ACTIVE_X = 102,
                    it_PANE_COMBO_BOX = 104,
                    it_COMBO_BOX = 113,
                    it_LINKED_BUTTON = 116,
                    it_PICTURE = 117,
                    it_EXTEDIT = 118,
                    it_CHECK_BOX = 121,
                    it_OPTION_BUTTON = 122,
                    it_MATRIX = 127,
                    it_GRID = 128,
                    it_BUTTON_COMBO = 129,
                 */
                            #endregion

                            switch (type)//懒得用工厂
                            {
                                case "4"://it_BUTTON
                                    package.Items.Add(Node2Item_4(node));
                                    break;
                                case "8"://it_EDIT
                                    package.Items.Add(Node2Item_4(node));
                                    break;
                                case "99"://it_FOLDER
                                    break;
                                case "113"://it_COMBO_BOX
                                    package.Items.Add(Node2Item_113(node));
                                    break;
                                case "121"://it_CHECK_BOX
                                    break;
                                case "127"://it_MATRIX
                                    package.Items.Add(Node2Item_127(node));
                                    break;
                            }
                        }
                    }
                }
                if (node.ChildNodes.Count > 0)
                {
                    InitLanguagePackage(node.ChildNodes, package);
                }
            }
        }

        #region 解析节点
        #region 解析it_BUTTON
        private Item Node2Item_4(XmlNode node)
        {
            /*
            <item uid="2" type="4" left="81" tab_order="0" width="65" top="545" height="20" visible="1" enabled="1" from_pane="0" to_pane="0" disp_desc="0" right_just="0" description="" linkto="" forecolor="-1" backcolor="-1" text_style="0" font_size="-1" supp_zeros="0" AffectsFormMode="1">
              <AutoManagedAttribute />
              <specific caption="取消" />
            </item>
             */
            Item item = new Item();
            item.Uid = node.Attributes["uid"].Value;
            item.Type = node.Attributes["type"].Value;
            item.Description = node.Attributes["description"] == null ? "" : node.Attributes["description"].Value;
            InitItem_4(node.ChildNodes, item);
            return item;
        }
        private void InitItem_4(XmlNodeList nodes, Item item)
        {
            //遍历+递归
            foreach (XmlNode node in nodes)
            {
                //处理XmlNode
                if (node.Name == "specific" && node.Attributes["caption"] != null)
                {
                    item.Caption = node.Attributes["caption"].Value;
                }

                if (node.ChildNodes.Count > 0)
                {
                    InitItem_4(node.ChildNodes, item);
                }
            }
        }
        #endregion
        #region 解析it_EDIT
        private Item Node2Item_8(XmlNode node)
        {
            return Node2Item_4(node);
        }
        #endregion
        private Item Node2Item_99(XmlNode node)
        {
            Item item = new Item();
            return item;
        }
        private Item Node2Item_113(XmlNode node)
        {
            Item item = new Item();
            item.Uid = node.Attributes["uid"].Value;
            item.Type = node.Attributes["type"].Value;
            item.Description = node.Attributes["description"].Value;
            foreach (XmlNode v in node.SelectNodes("./specific/ValidValues/action/ValidValue"))
            {
                ValidValue value = new ValidValue();
                value.Value = v.Attributes["value"].Value;
                value.Description = v.Attributes["description"].Value;
                item.ValidValues.Add(value);
            }
            return item;
        }
        private Item Node2Item_121(XmlNode node)
        {
            Item item = new Item();
            return item;
        }
        private Item Node2Item_127(XmlNode node)
        {
            Item item = new Item();
            item.Uid = node.Attributes["uid"].Value;
            item.Type = node.Attributes["type"].Value;
            item.Description = node.Attributes["description"].Value;
            InitItem_127(node.ChildNodes, item);
            return item;
        }
        #region 解析it_MATRIX
        private void InitItem_127(XmlNodeList nodes, Item item)
        {
            //遍历+递归
            foreach (XmlNode node in nodes)
            {
                //处理XmlNode
                if (node.Name == "column")
                {
                    Column column = new Column();
                    column.Uid = node.Attributes["uid"].Value;
                    column.Type = node.Attributes["type"].Value;
                    column.Title = node.Attributes["title"].Value;
                    column.Description = node.Attributes["description"].Value;
                    foreach (XmlNode v in node.ChildNodes)
                    {
                        if (v.Name == "ValidValues")
                        {
                            column.ValidValues = GetValidValues(v);
                        }
                    }
                    item.Columns.Add(column);
                }

                if (node.ChildNodes.Count > 0)
                {
                    InitItem_127(node.ChildNodes, item);
                }
            }
        }
        #endregion

        /// <summary>
        /// 懒得递归
        /// </summary>
        /// <param name="node"></param>
        /// <returns></returns>
        private List<ValidValue> GetValidValues(XmlNode node)
        {
            /*  <ValidValues>
                    <action type="add">
                        <ValidValue value="F" description="Forecast" />
                        <ValidValue value="C" description="Contract Actual" />
                        <ValidValue value="A" description="Payment Actual" />
                    </action>
                </ValidValues>
             */
            List<ValidValue> list = new List<ValidValue>();
            if (node.Name == "ValidValues")
            {
                foreach (XmlNode action in node.ChildNodes)
                {
                    if (action.Name == "action")
                    {
                        foreach (XmlNode v in action.ChildNodes)
                        {
                            if (v.Name == "ValidValue")
                            {
                                ValidValue vv = new ValidValue();
                                vv.Value = v.Attributes["value"].Value;
                                vv.Description = v.Attributes["description"].Value;
                                list.Add(vv);
                            }
                        }
                    }
                }
            }
            return list;
        }
        #endregion
        #endregion

        #region 根据语言包转换语言
        /// <summary>
        /// 翻译xml文件
        /// </summary>
        /// <param name="xml">要翻译的xml文件</param>
        /// <param name="dic">字典，键值对</param>
        public void Translate(XmlDocument xml, B1FormLanguagePackage package)
        {
            TranslateByRecursion(package, xml);
        }
        /// <summary>
        /// 递归语言包，对应翻译srf节点
        /// </summary>
        /// <param name="obj"></param>
        /// <param name="xml"></param>
        private void TranslateByRecursion(dynamic obj, XmlDocument xml)
        {
            string keyname = string.Empty;
            string keyvalue = string.Empty;
            Dictionary<string, string[]> translate_dictionary = new Dictionary<string, string[]>();
            List<ValidValue> validvalues = new List<ValidValue>();
            foreach (PropertyInfo pi in obj.GetType().GetProperties())
            {
                object[] key_attributes = pi.GetCustomAttributes(typeof(KeyAttribute), true);
                if (key_attributes.Length == 1)
                {
                    keyname = (key_attributes[0] as KeyAttribute).Element;
                    keyvalue = (pi.GetValue(obj, null) == null) ? "" : pi.GetValue(obj, null).ToString();
                }
                object[] translate_attributes = pi.GetCustomAttributes(typeof(TranslateAttribute), true);
                if (translate_attributes.Length == 1)
                {
                    string attr_value = pi.GetValue(obj, null) == null ? "" : pi.GetValue(obj, null).ToString();
                    string subnode_name = string.Empty;
                    object[] subnode_attrbutes = pi.GetCustomAttributes(typeof(SubNodeAttribute), true);
                    if (subnode_attrbutes.Length == 1)
                    {
                        subnode_name = (subnode_attrbutes[0] as SubNodeAttribute).Element;
                    }
                    translate_dictionary.Add(pi.Name.ToLower(), new string[] { attr_value, subnode_name });
                }
                if (pi.PropertyType.IsGenericType)//如果该属性是泛型
                {
                    if (pi.PropertyType != typeof(List<ValidValue>))
                    {
                        Type array_type = pi.PropertyType.GetGenericArguments()[0];//默认只有一个,因为我懒
                        IEnumerator array = (pi.GetValue(obj, null) as IEnumerable).GetEnumerator();
                        while (array.MoveNext())
                        {
                            dynamic item = array.Current;
                            TranslateByRecursion(item, xml);//递归
                        }
                    }
                    else
                    {
                        validvalues = pi.GetValue(obj, null) as List<ValidValue>;
                    }
                }
            }
            #region 替换翻译
            XmlNode node = xml.SelectSingleNode(String.Format("//*[@{0}='{1}']", keyname, keyvalue));
            if (node == null && ElementNoFoundEvent != null)
            {
                ElementNoFoundEvent(keyname, keyvalue);
            }
            if (validvalues.Count > 0)
            {
                XmlNodeList nodes = node.SelectNodes("./ValidValues/action/ValidValue");//srf中是不是一定这么出现？
                if (nodes.Count == 0)
                {
                    nodes = node.SelectNodes("./specific/ValidValues/action/ValidValue");//ComboBox里有个special
                }
                foreach (ValidValue v in validvalues)
                {
                    foreach (XmlNode v_node in nodes)
                    {
                        if (v_node.Attributes["value"].Value == v.Value)
                        {
                            (v_node as XmlElement).Attributes["description"].Value = v.Description;
                            continue;
                        }
                    }
                }
            }
            foreach (KeyValuePair<string, string[]> pair in translate_dictionary)
            {
                //扁平化后果然有问题，caption是item的子节点属性，而非当前节点属性，遍历取不到
                //foreach (XmlAttribute attribute in node.Attributes)
                //{
                //    if (pair.Key == attribute.Name.ToLower())
                //    {
                //        string[] value_subnode = translate_dictionary[pair.Key];
                //        if (!String.IsNullOrEmpty(value_subnode[1]))
                //        {
                //            XmlNode sub = node.SelectSingleNode(String.Format("./{0}",value_subnode[1]));
                //            (sub as XmlElement).Attributes[attribute.Name].Value = translate_dictionary[pair.Key][0];
                //        }
                //        else
                //        {
                //            (node as XmlElement).Attributes[attribute.Name].Value = translate_dictionary[pair.Key][0];
                //        }
                //        continue;
                //    }
                //}
                /*字典由语言包解析而来*/
                if (pair.Key == "caption")
                {
                    string[] value_subnode = translate_dictionary[pair.Key];
                    foreach (XmlNode sub in node.ChildNodes)
                    {
                        if (sub.Name == value_subnode[1])
                        {
                            if (sub.Attributes[pair.Key] != null)
                            {
                                (sub as XmlElement).Attributes[pair.Key].Value = value_subnode[0];
                            }
                        }
                    }
                }
                else
                {
                    foreach (XmlAttribute xmlattribute in node.Attributes)
                    {
                        if (pair.Key == xmlattribute.Name.ToLower())
                        {
                            (node as XmlElement).Attributes[xmlattribute.Name].Value = translate_dictionary[pair.Key][0];
                        }
                    }
                }
            }

            #endregion
        }
        /// <summary>
        /// 递归翻译节点
        /// </summary>
        /// <param name="nodes">要翻译的节点</param>
        private void TranslateNode(XmlNodeList nodes, B1FormLanguagePackage package)
        {
            //遍历+递归
            foreach (XmlNode node in nodes)
            {
                if (node.Name == "form")
                {
                    XmlElement xe = node as XmlElement;//将子节点类型转换为XmlElement
                    xe.SetAttribute("title", "");
                }
                //处理XmlNode
                if (node.Name == "item")
                {
                    XmlElement xe = node as XmlElement;//将子节点类型转换为XmlElement

                    string uid = node.Attributes["uid"].Value;
                    string type = node.Attributes["type"].Value;

                    if (uid == "2")
                    {
                        xe.SetAttribute("title", "啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊");
                    }
                }

                if (node.ChildNodes.Count > 0)
                {
                    TranslateNode(node.ChildNodes, package);
                }
            }
        }

        #endregion

        #region 根据Excel自动替换语言包语言
        public void AutoSwitchLanguage(B1FormLanguagePackage package, string excel, string sheet, string keycolumn, string valuecolumn, string descriptioncolummn)
        {
            DataTable dictionary = Utilities.ExcelToDataTable(excel, sheet);
            dictionary.Columns[keycolumn].ColumnName = "uid";
            dictionary.Columns[valuecolumn].ColumnName = "title";
            dictionary.Columns[descriptioncolummn].ColumnName = "descirption";
            SwitchByRecursion(package, dictionary);
        }
        private void SwitchByRecursion(dynamic obj, DataTable dictionary)
        {
            #region 替换翻译
            if (obj.GetType() == typeof(B1FormLanguagePackage))
            {
                foreach (Item item in obj.Items)
                {
                    SwitchByRecursion(item, dictionary);
                }
            }
            else if (obj.GetType() == typeof(Item))
            {
                string filterExpression = String.Format("{0}='{1}'", "uid", AnalyzeFieldName(obj.Uid));
                DataRow[] rows = dictionary.Select(filterExpression);
                if (rows.Length == 1)
                {
                    obj.Caption = rows[0]["title"].ToString();
                    obj.Description = rows[0]["description"].ToString();
                }
                foreach (Column column in obj.Columns)
                {
                    SwitchByRecursion(column, dictionary);
                }

            }
            else if (obj.GetType() == typeof(Column))
            {
                string filterExpression = String.Format("{0}='{1}'", "uid", AnalyzeFieldName(obj.Uid));
                DataRow[] rows = dictionary.Select(filterExpression);
                if (rows.Length == 1)
                {
                    obj.Title = rows[0]["title"].ToString();
                    obj.Description = rows[0]["description"].ToString();
                }
            }
            else if (obj.GetType() == typeof(ValidValue))
            { }

            #endregion
        }
        private string AnalyzeFieldName(string fullname)
        {
            int index = fullname.IndexOf('_');
            if (index > 0)
            {
                return fullname.Substring(index);
            }
            else
            {
                return fullname;
            }
        }
        #endregion
    }
}
